package com.minelx.datamicroscope.querylanguage.data.sql;

import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.minelx.datamicroscope.querylanguage.data.CollectingKey;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Stream.concat;

public class AliasedTables {

	private final Map<String, CollectingKey> aliasesToTableKeyMapping;

	private final List<TableAliasedSelectItem> joiningCollect;

	private final List<CollectingKey> orderedTableKeys;

	private final Map<CollectingKey, String> howMapping;

	AliasedTables(Map<String, CollectingKey> aliasesToTableKeyMapping,
				  List<TableAliasedSelectItem> joiningCollect,
				  List<CollectingKey> orderedTableKeys,
				  Map<CollectingKey, String> howMapping) {
		this.aliasesToTableKeyMapping = aliasesToTableKeyMapping;
		this.joiningCollect = joiningCollect;
		this.orderedTableKeys = orderedTableKeys;
		this.howMapping = howMapping;
	}

	List<TableAliasedSelectItem> createSelectItems(List<SQLSelectItem> commonSelectItems) {
		Stream<TableAliasedSelectItem> commonTableAliasedSelectItems = commonSelectItems.stream()
				.map(sqlSelectItem -> TableAliasedSelectItem.from(sqlSelectItem, aliasesToTableKeyMapping));
		List<TableAliasedSelectItem> allTableAliasedSelectItems = concat(commonTableAliasedSelectItems, joiningCollect.stream()).collect(toList());
		return orderSelectItems(allTableAliasedSelectItems, aliasesToTableKeyMapping, orderedTableKeys);
	}

	private List<TableAliasedSelectItem> orderSelectItems(List<TableAliasedSelectItem> allTableAliasedSelectItems,
												  Map<String, CollectingKey> aliasesToTableKeyMapping,
												  List<CollectingKey> orderedTableKeys) {
		SelectList allSelectList = new SelectList(aliasesToTableKeyMapping, allTableAliasedSelectItems);
		return orderedTableKeys.stream()
				.map(allSelectList::getSelectItemsBelongsTo)
				.flatMap(Collection::stream)
				.collect(toList());
	}

	public Map<CollectingKey, String> getHowMapping() {
		return howMapping;
	}
}
